#include "esp_log.h"
#include "esp_err.h"
#include "string.h"
#include "stdlib.h"
#include "user_max98357a.h"
#include "user_sdspi.h"
#include "user_ec11.h"
#include "driver/i2s.h"

static const char *TAG = "MAX98357A";

static int16_t i2s_readraw_buff[I2S_SAMPLE_SIZE];
size_t bytes_read;
const int WAVE_HEADER_SIZE = 44;

uint8_t play_index = 0;
// char wav_list[10];

struct wavinfo *wav_list = NULL;
struct wavinfo list[WAV_LIST_MAX];
int current_list_num = 0;
struct wavinfo current_wav_msg;
struct wavinfo temp_wavinfo;


void init_i2s(void)
{
    // Set the I2S configuration as PDM and 16bits per sample
    i2s_config_t i2s_config = {
        .mode = I2S_MODE_MASTER | I2S_MODE_RX  | I2S_MODE_TX , // | I2S_MODE_PDM,
        .sample_rate = I2S_REC_SAMPLE_RATE,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,
        .dma_buf_count = 8,
        .dma_buf_len = 1024,
        .use_apll = 0,
    };

    // Set the pinout configuration (set using menuconfig)
    i2s_pin_config_t pin_config = {
        .mck_io_num = I2S_PIN_NO_CHANGE,
        .bck_io_num = I2S_PIN_BCK_GPIO,
        .ws_io_num = I2S_PIN_WS_GPIO,
        .data_out_num = I2S_PIN_DATA_PLAYBACK,
        .data_in_num = -1,
    };

    // Call driver installation function before any I2S R/W operation.
    ESP_ERROR_CHECK( i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL) );
    ESP_ERROR_CHECK( i2s_set_pin(I2S_NUM, &pin_config) );
    ESP_ERROR_CHECK( i2s_set_clk(I2S_NUM, I2S_REC_SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO) );
}

void playback_wav(char *wav_name)
{
    printf("wav name is %s\n",wav_name);
    FILE* f_wav_play = fopen(wav_name, "r");
    if (f_wav_play == NULL) {
        ESP_LOGE(TAG, "Failed to open file for writing");
        return;
    }

    static int32_t index = 0;
    char wav_header_fmt_play[WAVE_HEADER_SIZE];

    fread(wav_header_fmt_play, 1, WAVE_HEADER_SIZE, f_wav_play);

    // printf("wav play head: %2x\n",wav_header_fmt_play[0]);

    char temp_cpr[8];
    strncpy(temp_cpr,wav_header_fmt_play,4);
    if(strstr(temp_cpr , "RIFF"))
    {
        // printf("this is wav file\n");
        strncpy(temp_cpr,wav_header_fmt_play+8,8);
        if(strstr(temp_cpr , "WAVEfmt "))
        {
            printf("this is wav file \n");

            current_wav_msg = get_wav_msg(wav_name);

            // wav size
            printf("wav size = %02x, %02x, %02x, %02x\n",wav_header_fmt_play[40],wav_header_fmt_play[41],wav_header_fmt_play[42],wav_header_fmt_play[43]);

            current_wav_msg.while_time = wav_header_fmt_play[40] + wav_header_fmt_play[41]* (1<<8) + wav_header_fmt_play[42]* (1<<16) + wav_header_fmt_play[43] * (1<<24);
            printf("while_time = %d\n",current_wav_msg.while_time);

            // wav sample rate
            current_wav_msg.sample_rate = wav_header_fmt_play[24] + wav_header_fmt_play[25]* (1<<8) + wav_header_fmt_play[26]* (1<<16) + wav_header_fmt_play[27] * (1<<24);
            printf("sample_rate = %d\n",current_wav_msg.sample_rate);

            int temp_current_time = 0;
            bytes_read = 0;

            // Start playback
            while (temp_current_time < current_wav_msg.while_time) {
                // Read the RAW samples from the microphone (char *)

                fread(i2s_readraw_buff, 1, bytes_read, f_wav_play);

                i2s_write(I2S_NUM, i2s_readraw_buff, I2S_SAMPLE_SIZE, &bytes_read, 100);

                temp_current_time += bytes_read;
                // Write the samples to the WAV file
                // printf("%ls\n",i2s_readraw_buff);
                // printf("temp_current_time = %d\n",temp_current_time);
                // vTaskDelay(1);
			
		
        	if(index != 0 && ec11_cnt != index)
	        {
        	    index = ec11_cnt;
		    break;
		}
		else if(ec11_cnt != index)
		{
        	    index = ec11_cnt;
		}
		
            }	

            if (temp_current_time >= current_wav_msg.while_time)
            {
                play_index++;
                if(play_index > current_list_num - 1)
                {
                    play_index = 0;
                }
            }
        }
    }

    // ESP_LOGI(TAG, "Recording done!");
    fclose(f_wav_play);
    ESP_LOGI(TAG, "File read from SDCard");

}


void generate_wav_header(char* wav_header, uint32_t wav_size, uint32_t sample_rate){

    // See this for reference: http://soundfile.sapp.org/doc/WaveFormat/
    uint32_t file_size = wav_size + WAVE_HEADER_SIZE - 8;
    uint32_t byte_rate = I2S_BYTE_RATE;

    const char set_wav_header[] = {
        'R','I','F','F', // ChunkID
        file_size, file_size >> 8, file_size >> 16, file_size >> 24, // ChunkSize
        'W','A','V','E', // Format
        'f','m','t',' ', // Subchunk1ID
        0x10, 0x00, 0x00, 0x00, // Subchunk1Size (16 for PCM)
        0x01, 0x00, // AudioFormat (1 for PCM)
        0x01, 0x00, // NumChannels (1 channel)
        sample_rate, sample_rate >> 8, sample_rate >> 16, sample_rate >> 24, // SampleRate
        byte_rate, byte_rate >> 8, byte_rate >> 16, byte_rate >> 24, // ByteRate
        0x02, 0x00, // BlockAlign
        0x10, 0x00, // BitsPerSample (16 bits)
        'd','a','t','a', // Subchunk2ID
        wav_size, wav_size >> 8, wav_size >> 16, wav_size >> 24, // Subchunk2Size
    };

    memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}

void music_play(char *name)
{
    init_i2s();

    playback_wav(name);

    ESP_ERROR_CHECK( i2s_driver_uninstall(I2S_NUM) );
}

void user_max98357a_task(void *args)
{
    play_index = 0;
    static uint8_t index = 0;

    while(1)
    {
        if(ec11_cnt != index)
        {
            index = ec11_cnt;
	    printf("%s index:%d %s\r\n",__func__, index, list[index].name);
            //playback_wav(list[index].name);
	    music_play(list[index].name);
        }
        vTaskDelay(10);
    }
}
